Для создания литерала строки в IL коде есть специальная команда ldstr, вместо обычного создания объекта через команду newobj
==Важно!
На момент компиляции, все литералы строк попадают в метаданные.
==
По соображением производительности тип стринг слишком сильно интегрирован в CLR. В частности CLR точно знает расположение полей в этом типе и обращается к ним напрямую. По этой причине, string пришлось закрыть от наследования sealed . (Иначе бы, если бы люди могли наследоваться, они бы могли добавлять поля, а значит CLR бы перестраивал порядок полей и все бы падало)
Рихтер крайне рекомендует использовать для сравнения следующие методы:
(тк их поведение предсказуемо)
Чтобы менять, игнорировать регистр или нет, можно передавать параметр comparationType. Этот параметр принимает енамчик и в нем есть разные типы сравнений. Также существуют другие параметры включающие другие нюансы сравнения и они могут изменяться через параметр CompareOption (если есть)
Обрати внимание, если мы сравниваем с игнорированием регистра то лучше приводить обе строки к верхнему регистру, т.к. майскрософт оптимизировал сравнение строк только в верхнем регистре. (Если передавать флаг игнорирования регистра, то он под капотом так и сделает, просто приведет к верхнему)
Стоит следить за спец символами из левых языков если при сравнении включаешь флаг cultureInfo, т.к. шарпы подтягивают региональные стандарты языка на компе и могут считать одним и тем же например немецкую букву бетта и два символа ss (видимо у них на клавиатуре для ввода бетты пишут дважды s, хер знает, но такое бывает)
Если ты ожидаешь что будет много одинаковых строк в процессе работы приложения, то нужно применять интернирование строк.
Алгоритм работы Интернирования в общем:
Следует обратить внимание, что объект таблицы будет убит и за ним придет сборщик, только в случае, если приложение будет остановлено. А значит все строки которые были туда добавлены не будут убираться сборщиком. Этим и достигается то, что интернированые однажды строки будут всегда жить и их можно будет переиспользовать в других местах.
По умолчанию, все литералы строк, которые находятся в методанных, интернируются при запуске приложения. Однако, существует атрибут сборки который это запрещает
[assembly: System.Runtime.CompilerServices.CompilationRelaxations(CompilationRelaxations.NoStringInterning)]
, более того, он всегда ставится при комиляции, однако, clr его не слушается и все равно проводит интернирование, НО, стоит помнить, что он не обязан его делать, поэтому строить логику на том, что интернирование произойдет автоматически - опасно.
Пример использования интернирования:
private static int32 SearchWord(String word, String[] wordList){
Int32 count = 0;
for (Int32 i = 0; i < wordList.Length; i++){
if(wordList[i].Equals(word)){
count++;
}
}
return count;
}
В этом примере clr придется на каждое слово из массива провдить посимвольное сравнение, при том, что слова в этом массиве могут повторяться, это долго.
private static int32 SearchWord(String word, String[] wordList){
// подразумевается, что все слова в листе уже интернированы.
Int32 count = 0;
word = String.Intern(word);
for (Int32 i = 0; i < wordList.Length; i++){
if(Object.ReferenceEquals(wordList[i], word)){
count++;
}
}
return count;
}
В таком случае он будет сравнивать по ссылке, что быстрее чем перебор каждого символа в каждой строке списка.
Пока я разбирался в нем, я согласился с Рихтером что нахуй он вообще нужен.
Алгоритм:
Для сранвния именно ссылок можно применять статический метод Object.ReferenceEquals()
В версиях дотнета начиная с 7 были добавлены эти структуры, они являются оберткой над указателями в безопасном коде. Span применяется в рамках одного метода и не может передаваться, а Memory может передаваться. Они используются чтобы не пересоздавать строку или массив если хочешь работаь только с её частью.
“image.png” could not be found.
Так, можно будет работать только с кусочком строки, не создавая подстроку.
Для строки AsSpan возвращает только ридонли, так что менять не получиться
Также был добавлен конструкор
string(Span<Char>)
Также был добавлен сахар, такой, что теперь можно пистаь так
var str = string(”literal”);
Для того чтобы создать еще одну ссылку на существующую строку есть два варианта
var newLink = oldLink
var newLink = oldLink.Clone()
Для создания нового экземпляра полностью, есть два варианта
Под капотом имеет динамический массив символов чар. Стоит помнить, что при расширении массива происходит полное перекопированние элементов в расширенный массив
В шарпе можно использовать класс который является АПИ для взаимодействия с неуправляемой кучей, это нужно например для работы с паролями, так как в управляемой куче пароли даже после удаления объекта могут долго висеть до сборки мусора, и их можно будет прочитать другим неуправляемым кодом
SecureString предоставляет возможность читать и добавлять символы в конец строки, шифрует символы, а также поддерживает IDispose
Однако, его использование считает устаревшим, так как он сильно усложняет код, сейчас гпт рекомендует просто хранить символы пароля в массиве на стеке.